package org.zero.onlinesubject.service.impl;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.cj.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.zero.onlinesubject.common.constant.RedisConstant;
import org.zero.onlinesubject.common.param.LiveRoomParam;
import org.zero.onlinesubject.common.vo.LiveRoomVo;
import org.zero.onlinesubject.common.vo.Result;
import org.zero.onlinesubject.common.vo.UserVo;
import org.zero.onlinesubject.entity.*;
import org.zero.onlinesubject.mapper.MinWordMapper;
import org.zero.onlinesubject.mapper.SystemFileMapper;
import org.zero.onlinesubject.mapper.UserMapper;
import org.zero.onlinesubject.service.LiveRoomService;
import org.zero.onlinesubject.mapper.LiveRoomMapper;
import org.springframework.stereotype.Service;
import org.zero.onlinesubject.service.SignRecordsService;
import org.zero.onlinesubject.service.UserService;
import org.zero.onlinesubject.utils.DataDesensitizationUtil;
import org.zero.onlinesubject.utils.UserContextHolder;
import org.zero.onlinesubject.utils.WordUtil;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 *
 */
@Service
public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomMapper, LiveRoom>
    implements LiveRoomService{

    @Value("${file.external_path}")
    private String externalPath;

    @Value("${live.url}")
    private String liveUrl;

    private final Map<String,String> liveState = new HashMap<>();

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private LiveRoomMapper liveRoomMapper;

    @Resource
    private SystemFileMapper systemFileMapper;

    @Resource
    private UserService userService;

    @Resource
    private ThreadService threadService;

    @Resource
    private MinWordMapper minWordMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private SignRecordsService signRecordsService;

    @PostConstruct
    private void initMap(){
        liveState.put("0001","未开始");
        liveState.put("0002","进行中");
        liveState.put("0003","已结束");

        List<MinWord> wordsList = minWordMapper.selectList(null);
        List<String> words = new ArrayList<>();
        wordsList.forEach(word->{
            words.add(word.getContent());
        });

        WordUtil.init(words);
    }

    @Override
    public Boolean isTimeConflict(String startTime) {
        return liveRoomMapper.isTimeConfict(startTime) == 0;
    }

    @Override
    public Result<LiveRoomVo> getLiveInfo(String liveId) {
        User user = UserContextHolder.get();
        updateLearnCount(stringRedisTemplate, userMapper,user);

        LiveRoom liveRoom = liveRoomMapper.selectById(liveId);
        if(liveRoom == null){
            return Result.error(500,"直播间信息不存在");
        }
        String uid = liveRoom.getUserid();

        UserVo userVo = userService.getUserVo(uid);
        DataDesensitizationUtil.desensitizeUserData(userVo);

        LiveRoomVo roomVo = new LiveRoomVo();
        BeanUtils.copyProperties(liveRoom,roomVo);
        String link = roomVo.getLivelink();
        if(link.endsWith(".mp4")){
            QueryWrapper<SystemFile> wrapper = new QueryWrapper<>();
            wrapper.select("FilePath").eq("BizID",liveId).last(" limit 1");
            SystemFile systemFile = systemFileMapper.selectOne(wrapper);
            if(systemFile==null){
                return Result.error(500,"当前直播内容还未转换完成");
            }
            link = systemFile.getFilepath();
        }

        roomVo.setLivestate(liveState.get(roomVo.getLivestate()));
        roomVo.setLivelink(liveUrl + link);
        roomVo.setLivecover(externalPath + roomVo.getLivecover());
        roomVo.setUserVo(userVo);

        return Result.ok(roomVo);
    }

    public void updateLearnCount(StringRedisTemplate stringRedisTemplate, UserMapper userMapper,User user) {
        String userid = user.getUserid();
        String username = user.getUsername();
        LocalDateTime now = LocalDateTime.now();
        int day = now.getDayOfMonth();
        String format = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        String key = RedisConstant.DAY_LEARN_COUNT + username + format;

        if (Boolean.FALSE.equals(stringRedisTemplate.opsForValue().getBit(key, day))) {
            UpdateWrapper<User> wrapper = new UpdateWrapper<>();
            wrapper.set("LearnCount",user.getLearnCount() + 1).eq("UserID",userid).last(" limit 1");
            userMapper.update(wrapper);
            stringRedisTemplate.opsForValue().setBit(key,day,true);
        }
    }

    @Override
    public Result<String> saveLive(LiveRoomParam param) {
        String userid = UserContextHolder.get().getUserid();
        LiveRoom liveRoom = new LiveRoom();
        liveRoom.setLiveid(param.getLiveRoomId());
        liveRoom.setLivename(param.getLiveTitle());
        liveRoom.setUserid(userid);
        String livelink = "/" + UUID.randomUUID().toString(true) + "/"+"live.flv";
        liveRoom.setLivelink(livelink);
        liveRoom.setDescription(param.getLiveDescription());
        liveRoom.setLivecover(param.getLivecover());
        liveRoom.setLivetag(param.getTagType());
        liveRoom.setLivestate("0001");
        liveRoom.setViewercount(0);
        liveRoom.setLive(false);
        LocalDateTime start = LocalDateTime.parse(param.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse(param.getEndTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        liveRoom.setStartdate(start);
        liveRoom.setEnddate(end);

        boolean b = save(liveRoom);
        if(!b){
            return Result.error(500,"添加直播任务失败,请重试");
        }

        liveRoom.setLivestate(liveState.get(liveRoom.getLivestate()));
        liveRoom.setLivelink(livelink);
        liveRoom.setLivecover(externalPath + liveRoom.getLivecover());
        liveRoom.setUserid(userid);
        threadService.addLiveRoomCache(stringRedisTemplate,liveRoom,userid);
        return Result.ok("添加直播任务成功");
    }

    @Override
    public List<LiveRoom> getLiveList(String liveName,Integer current,Integer size) {
        QueryWrapper<LiveRoom> wrapper = new QueryWrapper<>();
        wrapper.like(!StringUtils.isNullOrEmpty(liveName),"LiveName","%"+liveName+"%").orderByDesc("ViewerCount").last(" limit "+current+","+size);

        List<LiveRoom> list = list(wrapper);
        list.forEach(room->{
            room.setLivestate(liveState.get(room.getLivestate()));
            room.setLivelink(liveUrl + room.getLivelink());
            room.setLivecover(externalPath + room.getLivecover());
        });
        return list;
    }

    @Override
    public List<LiveRoom> getOwnLive() {
        User user = UserContextHolder.get();
        List<LiveRoom> list = null;
        if(Boolean.TRUE.equals(stringRedisTemplate.hasKey(RedisConstant.LIVE_ROOM_USER+user.getUserid()))){
            String body = stringRedisTemplate.opsForValue().get(RedisConstant.LIVE_ROOM_USER + user.getUserid());
            list = JSON.parseObject(body,new TypeReference<List<LiveRoom>>(){});
        }
        if(list==null){
            list = liveRoomMapper.getOwnLive(user.getUserid());
            list.forEach(room->{
                room.setLivestate(liveState.get(room.getLivestate()));
                room.setLivelink(liveUrl + room.getLivelink());
                room.setLivecover(externalPath + room.getLivecover());
            });
            stringRedisTemplate.opsForValue().set(RedisConstant.LIVE_ROOM_USER+user.getUserid(), JSON.toJSONString(list),10, TimeUnit.MINUTES);
        }
        return list;
    }

    @Override
    public boolean updateViewCount(String liveId) {
        int rows = liveRoomMapper.updateViewCount(liveId);
        return rows!=0;
    }

    @Override
    public Boolean updateLive(String liveId, Boolean state) {
        UpdateWrapper<LiveRoom> wrapper = new UpdateWrapper<>();
        wrapper.set("Live",state).eq("LiveID",liveId).last(" limit 1");
        int rows = liveRoomMapper.update(wrapper);
        stringRedisTemplate.delete(RedisConstant.LIVE_ROOM_USER + UserContextHolder.get().getUserid());
        return rows!=0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteLive(String liveId) {
        QueryWrapper<LiveRoom> wrapper = new QueryWrapper<>();
        wrapper.eq("LiveID",liveId).last(" limit 1");
        Boolean flag = remove(wrapper);

        QueryWrapper<SignRecords> wrapper2 = new QueryWrapper<>();
        wrapper.eq("LiveID",liveId);
        Boolean flag2 = signRecordsService.remove(wrapper2);

        QueryWrapper<SystemFile> wrapper3 = new QueryWrapper<>();
        wrapper3.eq("BizID",liveId);
        Boolean flag3 = systemFileMapper.delete(wrapper3)!=0;

        stringRedisTemplate.delete(RedisConstant.LIVE_ROOM_USER + UserContextHolder.get().getUserid());
        return flag && flag2 && flag3;
    }
}




